/**
 * @ProjectName: go-learn-demo
 * @PackageName: _1_mysql
 * @Description: gorm：建立对象和数据库表的字段映射关系
 * @Author: hy.bai
 * @Date: 2025-08-04 11:32
 */
package gormmysql

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"log/slog"
	"time"
)

// 建立对象和数据库表的映射关系
// 定义一个结构体，基于结构体去创建表，和对表的CRUD操作。
type UserModel struct { // User表的结构体ORM映射
	// 注意：属性生成列名时，默认是基于驼峰命名实现的
	Id           int32      `gorm:"primaryKey" json:"id"`                          // gorm:"primaryKey"是gorm框架标签，指定表的主键
	Name         string     `json:"name" gorm:"size:255;comment:'用户名'"`            // 设置字段的大小为255个字节
	Age          int32      `json:"age"`                                           // 设置Age字段
	Email        string     `json:"email" gorm:"type:varchar(64)"`                 // 唯一索引
	CreatedAt    *time.Time `json:"createdAt" gorm:"column:create_time"`           // 指定列名
	MemberNumber string     `json:"memberNumber" gorm:"column:mn;unique;not null"` // 设置memberNumber字段唯一且不为空
	Num          int32      `json:"num" gorm:"not null"`                           // 设置Num字段非空且自增(gorm:"not null;autoIncrement")会报错
	IgnoreMe     int        `gorm:"-"`                                             // 忽略这个字段
}

// 自定义表名，默认情况下，表名是结构体的名字以复数形式，且符合驼峰命名
func (*UserModel) TableName() string {
	return "t_user_model"
}

// 测试创建表
func TestModel() {
	// 1.拼接URL地址
	dns := "root:root@tcp(127.0.0.1:3308)/test?charset=utf8mb4&parseTime=True&loc=Local"
	// parseTime是查询结果是否自动解析为时间类型,即：time.Time类型，对应的数据库中的类型是：datetime
	// loc是Mysql的时区设置
	// 2.创建gorm的配置对象
	// 定义gorm的配置,打印Sql日志
	gConfig := &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
		// DryRun: true, // 默认为false，表示生成SQL语句，而不执行
	}
	db, err := gorm.Open(mysql.Open(dns), gConfig)
	if err != nil {
		panic(fmt.Sprintf("failed to connect database, reason:%s", err.Error())) // 抛出Panic异常，终止代码的执行。
	}
	// 2.自动建表。AutoMigrate:自动迁移
	var userModel UserModel // 声明一个结构体
	ctErr := db.Debug().Set("gorm:table_options", " COMMENT='用户信息表(用于测试Model)'").AutoMigrate(userModel)
	if ctErr != nil {
		panic(fmt.Sprintf("failed to create table, reason:%s", ctErr.Error())) // 抛出Panic异常，终止代码的执行。
	}
	slog.Info("Mysql数据库相关操作执行完成~~~")
}
